package is.server.model.xtool;

import is.common.exception.RowNotFoundException;
import is.common.exception.RowsAreaIncorrectException;
import is.common.exception.UniqueCheckFailedException;
import is.common.interfaces.SectionAdapter;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * @author aspr0
 *         Date: 17.04.12
 *         Time: 15:17
 */
public class EmployeeSectionAdapter extends AbstractSectionAdapter implements SectionAdapter
{
    public EmployeeSectionAdapter(Node section, NodeList rows, SectionArbiter sectionArbiter)
    {
        super(section, rows, sectionArbiter);
    }


    @Override
    public String[][] getRows(int rowNumStart, int howMany) throws RowsAreaIncorrectException, RowNotFoundException
    {
        if (howMany < 1)
        {
            howMany = rowCount;
        }

        rowsAreaExists(rowNumStart, howMany, rowCount);

        return getRowsReplacementsMade(rowNumStart, howMany);
    }

    public String[] getHeader()
    {
        return Name.Out.Employee.entries;
    }

    public NodeList createRow()
    {
        return super.createRow(Name.Tag.Employee.entries);
    }

    /**
     * @param row
     * @throws RowNotFoundException if specified department not found
     */
    @Override
    public void addRow(String[] row) throws RowNotFoundException, UniqueCheckFailedException
    {

        String lastName = row[0];
        String firstName = row[1];
        String middleName = row[2];

        nameUnique(lastName, firstName, middleName);

        String departmentName = row[3];

        String departmentId = getDepartmentId(departmentName);
        row[3] = departmentId;

        NodeList createdRow = createRow();
        updateRowCount();

        String id = getId();
        incId();
        createdRow.item(0).setTextContent(id);

        int entryNum = 1;
        for (String entry : row)
        {
            createdRow.item(entryNum++).setTextContent(entry);
        }
    }

    @Override
    public void editRow(String[] rowStrings) throws UniqueCheckFailedException, RowNotFoundException
    {
        String id = rowStrings[0];
        String departmentName = rowStrings[4];

        nameUniqueExceptCurrentId(rowStrings);
        NodeList rowNodeList = getRowById(id);
        rowStrings[4] = getDepartmentId(departmentName);
        /* in edit case the name may remain the same so given row shouldn't be compared with itself */
        nameUniqueExceptCurrentId(rowStrings);

        int entryNum = 0;
        for (String entry : rowStrings)
        {
            rowNodeList.item(entryNum++).setTextContent(entry);
        }
    }

    @Override
    public Node createSection()
    {
        return null;
    }

    public String[] getName(String bossId) throws RowNotFoundException
    {
        for (int rowNum = 0; rowNum < rowCount; rowNum++)
        {
            NodeList row = section.getChildNodes().item(rowNum).getChildNodes();

            String currentBossId = row.item(0).getTextContent();
            String currentBossLastName = row.item(1).getTextContent();
            String currentBossFirstName = row.item(2).getTextContent();
            String currentBossMiddleName = row.item(3).getTextContent();

            if (currentBossId.equals(bossId))
            {
                return new String[]{currentBossLastName, currentBossFirstName, currentBossMiddleName};
            }
        }

        throw new RowNotFoundException();
    }

    protected String[][] getRowsReplacementsMade(int rowNumStart, int howMany) throws RowNotFoundException
    {
        String[][] rowsStrings = new String[howMany][Name.Out.Employee.entries.length];

        for (int rowNum = rowNumStart; rowNum < rowNumStart + howMany; rowNum++)
        {
            /* starting output row */
            int entryOutputNum = 0;

            for (int entryNum = 0; entryNum < Name.Tag.Employee.entries.length; entryNum++)
            {
                String entryValue = rows.item(rowNum).getChildNodes().item(entryNum).getTextContent();
                switch (entryNum)
                {
                    case 4:
                        rowsStrings[rowNum][entryOutputNum++] = sectionArbiter.getDepartmentName(entryValue);
                        break;

                    default:
                        rowsStrings[rowNum][entryOutputNum++] = entryValue;
                        break;
                }
            }
        }
        return rowsStrings;
    }

    protected void nameUniqueExceptCurrentId(String[] row) throws UniqueCheckFailedException
    {
        String id = row[0];
        String lastName = row[1];
        String firstName = row[2];
        String middleName = row[3];

        for (int rowNum = 0; rowNum < rowCount; rowNum++)
        {
            NodeList entries = rows.item(rowNum).getChildNodes();
            String currentId = entries.item(0).getTextContent();
            String currentLastName = entries.item(1).getTextContent();
            String currentFirstName = entries.item(2).getTextContent();
            String currentMiddleName = entries.item(3).getTextContent();

            if (!currentId.equals(id))
            {
                if (currentLastName.equals(lastName))
                {
                    if (currentFirstName.equals(firstName))
                    {
                        if (currentMiddleName.equals(middleName))
                        {
                            throw new UniqueCheckFailedException();
                        }
                    }
                }
            }
        }

    }

    public void nameUnique(String lastName, String firstName, String middleName) throws UniqueCheckFailedException
    {
        for (int rowNum = 0; rowNum < rowCount; rowNum++)
        {
            NodeList entries = rows.item(rowNum).getChildNodes();
            String currentLastName = entries.item(1).getTextContent();
            String currentFirstName = entries.item(2).getTextContent();
            String currentMiddleName = entries.item(3).getTextContent();

            if (currentLastName.equals(lastName))
            {
                if (currentFirstName.equals(firstName))
                {
                    if (currentMiddleName.equals(middleName))
                    {
                        throw new UniqueCheckFailedException();
                    }
                }
            }
        }
    }

    private String getDepartmentId(String departmentName) throws RowNotFoundException
    {
        return sectionArbiter.getDepartmentId(departmentName);
    }

    public void idExists(String id) throws RowNotFoundException
    {
        if (!isThereSuchEntry(0, id))
        {
            throw new RowNotFoundException();
        }
    }

    public void inDepartment(String id, String departmentId) throws RowNotFoundException
    {
        for (int rowNum = 0; rowNum < rowCount; rowNum++)
        {
            NodeList entries = rows.item(rowNum).getChildNodes();
            String currentId = entries.item(0).getTextContent();
            String currentDepartmentId = entries.item(4).getTextContent();

            if (id.equals(currentId))
            {
                if (departmentId.equals(currentDepartmentId))
                {
                    return;
                }
                else
                {
                    throw new RowNotFoundException();
                }
            }
        }
    }

    public boolean isDepartmentEmpty(String departmentId)
    {
        for (int rowNum = 0; rowNum < rowCount; rowNum++)
        {
            NodeList entries = rows.item(rowNum).getChildNodes();
            String currentDepartmentId = entries.item(4).getTextContent();

            if (currentDepartmentId.equals(departmentId))
            {
                return false;
            }
        }
        return true;
    }
}
